package com.huajx.cseek.face.server;

import com.ha.facecamera.configserver.ConfigServer;
import com.ha.facecamera.configserver.ConfigServerConfig;
import com.ha.facecamera.configserver.pojo.Face;
import com.ha.facecamera.configserver.pojo.FacePage;
import com.ha.facecamera.configserver.pojo.ListFaceCriteria;
import com.huajx.core.Hboot;
import com.huajx.core.config.HbootConfigManager;
import com.huajx.core.kit.AsyncHttpClientKit;
import com.huajx.core.kit.HttpKit;
import com.huajx.core.server.HbootServer;
import com.huajx.core.server.annonation.MinaServer;
import com.huajx.core.server.config.HbootServerConfig;
import com.huajx.cseek.face.FaceCommand;
import com.huajx.cseek.face.QnyfUpload;
import com.huajx.cseek.face.StudentFace;

import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.huajx.cseek.face.config.CseekConfig;
import com.huajx.util.ObjectUtil;
import com.huajx.util.StrUtil;
import com.huajx.util.collection.CollectionUtil;
import com.qiniu.common.QiniuException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@MinaServer(name = "cseekConfig", port = 10001)
public class CseekConfigServer implements HbootServer {
    private static final Logger logger = LoggerFactory.getLogger(CseekConfigServer.class);

    private static ConfigServer configServer;
    public static final int DEFAULT_PORT = 10001;
    private static boolean isRunning;

    private String serverName;
    private int port;

    private String describe;

    private static String serverUrl = Hboot.config(CseekConfig.class).getServerUrl();

    @Override
    public void start() {
        isRunning = startConfigService(port);

        if (isRunning) {
            logger.info("{} 配置服务正在启动", serverName);

            configServer.onAuthing((time, username, password) -> {
                // XXX 如果要校验用户名密码，请使用如下代码
                //return username.equals("xiaohe") && Util.judgeRegPassword(time, "123456", password);
                logger.info("{} 收到鉴权消息username=>{} password=>{}", serverName, username, password);
                return true;
            });

            configServer.onCameraConnected((val) -> {
                logger.info("{} 设备已连接-数据端口:{}, {}", serverName, val, describe);
                Map<String, String > paras = new HashMap<>();
                paras.put("sn", val);
                try {
                    HttpKit.post(serverUrl + "/fm/studentFaceCommand/command", paras);
                } catch (IOException e) {
                    e.printStackTrace();
                }
//                AsyncHttpClientKit.post(serverUrl + "/fm/studentFaceCommand/command", paras, content -> {
//                    logger.info(content);
//                });
            });

            configServer.onCameraDisconnected((val) -> {
                logger.info("{} 设备已断开-数据端口:{}, {}", serverName, val, describe);
            });

        }

        logger.info("{} 服务启动完毕，监听端口:{}, {}", serverName, port, describe);
    }

    @Override
    public void stop() {
        if (!isRunning) {
            logger.warn("{}服务器已经停止！", serverName);
        } else {
            configServer.stop();
            isRunning = false;
        }
    }

    @Override
    public boolean isRunning() {
        return isRunning;
    }

    @Override
    public void config(HbootServerConfig config) {
        this.port = config.getPort() <= 80 ? DEFAULT_PORT : config.getPort();
        this.serverName = config.getName();
        this.describe = config.getDescribe();
    }

    /**
     * 配置服务器启动
     *
     * @param outPort 人脸相机外网穿透端口
     * @return
     */
    private static Boolean startConfigService(int outPort) {
        configServer = new ConfigServer();
        ConfigServerConfig serverConfig = new ConfigServerConfig();
        serverConfig.heartBeatInterval = 60;
        return configServer.start(outPort, serverConfig);
    }

    /**
     * 人脸相机图像添加
     *
     * @param faceCommand
     * @return
     */
    public static Boolean addFace(FaceCommand faceCommand) {//String machineId,String name,String cardId,int role ,String path
        if (faceCommand == null) {
            logger.info("命令为空！");
            return false;
        }
        if (configServer == null) {
            faceCommand.setStatus(2);
            faceCommand.setMsg("人脸相机服务为空");
            logger.info("人脸相机服务为空");
            return false;
        }
        if (!isRunning) {
            faceCommand.setStatus(2);
            faceCommand.setMsg("人脸相机服务未启动");
            logger.info("人脸相机服务未启动");
            return false;
        }
        String sn = faceCommand.getApparatusId();
        String faceid = faceCommand.getFaceid();
        if (StrUtil.isBlank(sn)) {
            faceCommand.setStatus(2);
            faceCommand.setMsg("人脸相机机器序列号为空");
            logger.info("人脸相机机器序列号为空");
            return false;
        }
        if (StrUtil.isBlank(faceid)) {
            faceCommand.setStatus(2);
            faceCommand.setMsg("人脸相机机器序学号为空");
            logger.info("人脸相机机器序学号为空");
            return false;
        }
        if (!configServer.getCameraOnlineState(sn)) {
            faceCommand.setStatus(3);
            faceCommand.setMsg("人脸相机机器序列号{}机器不在线！");
            logger.info("人脸相机机器序列号{}机器不在线！", sn);
            return false;
        }
        StudentFace studentFace = new StudentFace(faceCommand.getName(), faceid, faceCommand.getRole(), faceCommand.getPath());

        Face face = studentFace.getFace();
        if (face == null) {
            faceCommand.setStatus(2);
            faceCommand.setMsg("人脸头像路径不正确！！");
            logger.info("人脸头像路径不正确！！");
            return false;
        }
        boolean flag = configServer.addFace(sn, face, 5000);
        if (flag) {
            logger.info("添加人脸成功");
            faceCommand.setMsg("添加人脸成功！！");
            faceCommand.setStatus(1);
            return true;
        } else {
            if (configServer.getLastErrorCode() == 1283) {
                logger.info("学号为{}的学生，学生人脸已经存在", faceid);
                Boolean flag2 = modifyFace(faceCommand);
                if (flag2) {
                    faceCommand.setStatus(1);
                    faceCommand.setMsg("人脸机器数据已经存在，修改成功！");
                    logger.info("人脸机器数据已经存在，修改成功:{}", configServer.getLastErrorMsg());
                    return true;
                } else {
                    faceCommand.setStatus(2);
                    faceCommand.setMsg("人脸机器数据已经存在,修改失败");
                    logger.info("人脸机器数据已经存在，修改失败:{}", configServer.getLastErrorMsg());
                    return false;
                }
            } else {
                faceCommand.setStatus(2);
                faceCommand.setMsg(configServer.getLastErrorMsg());
                logger.info("人脸相机添加失败:{}", configServer.getLastErrorMsg());
                return false;
            }
        }
    }

    /**
     * 人脸相机图像更新
     *
     * @param faceCommand
     * @return
     */
    public static Boolean modifyFace(FaceCommand faceCommand) {
        if (faceCommand == null) {
            logger.info("命令为空！");
            return false;
        }
        if (configServer == null) {
            faceCommand.setStatus(2);
            faceCommand.setMsg("人脸相机服务为空");
            logger.info("人脸相机服务为空");
            return false;
        }
        if (!isRunning) {
            faceCommand.setStatus(2);
            faceCommand.setMsg("人脸相机服务未启动");
            logger.info("人脸相机服务未启动");
            return false;
        }
        String sn = faceCommand.getApparatusId();
        String faceid = faceCommand.getFaceid();
        if (StrUtil.isBlank(sn)) {
            faceCommand.setStatus(2);
            faceCommand.setMsg("人脸相机机器序列号为空");
            logger.info("人脸相机机器序列号为空");
            return false;
        }
        if (StrUtil.isBlank(faceid)) {
            faceCommand.setStatus(2);
            faceCommand.setMsg("人脸相机机器序学号为空");
            logger.info("人脸相机机器序学号为空");
            return false;
        }
        if (!configServer.getCameraOnlineState(sn)) {
            faceCommand.setStatus(3);
            faceCommand.setMsg("人脸相机机器序列号{}机器不在线！");
            logger.info("人脸相机机器序列号{}机器不在线！", sn);
            return false;
        }

        StudentFace studentFace = new StudentFace(faceCommand.getName(), faceid, faceCommand.getRole(), faceCommand.getPath());

        Face face = studentFace.getFace();
        if (face == null) {
            faceCommand.setStatus(2);
            faceCommand.setMsg("人脸头像路径不正确！！");
            logger.info("人脸头像路径不正确！！");
            return false;
        }
        boolean falg = configServer.modifyFace(sn, face, 5000);
        if (falg) {
            logger.info("更新人脸成功");
            faceCommand.setMsg("更新人脸成功！！");
            faceCommand.setStatus(1);
            return true;
        } else {
            if (configServer.getLastErrorCode() == 1539) {
                if (addFace(faceCommand)) {
                    faceCommand.setStatus(1);
                    faceCommand.setMsg("人脸相机当中没有该学生,加入该学生成功");
                    logger.info("人脸相机当中没有该学生,加入该学生成功:", configServer.getLastErrorMsg());
                    return true;
                } else {
                    faceCommand.setStatus(2);
                    faceCommand.setMsg("人脸相机当中没有该学生,加入该学生失败");
                    logger.info("人脸相机当中没有该学生,加入该学生失败:{}", configServer.getLastErrorMsg());
                    return false;
                }
            } else {
                faceCommand.setStatus(2);
                faceCommand.setMsg("人脸相机学生更新失败");
                logger.info("人脸相机学生更新失败:{}", configServer.getLastErrorMsg());
                return false;
            }
        }
        /*if (configServer != null && faceCommand != null
                && configServer.getCameraOnlineState(faceCommand.getApparatusId())
                && isRunning) {
            StudentFace studentFace = new StudentFace(faceCommand.getName(), faceCommand.getFaceid(), faceCommand.getRole(), faceCommand.getPath());
            if (studentFace.getFace() == null) {
                faceCommand.setStatus(2);
                faceCommand.setMsg("人脸头像路径不正确！！");
                logger.info("人脸头像路径不正确！！");
                return false;
            }
            if (configServer.modifyFace(faceCommand.getApparatusId(), studentFace.getFace(), 5000)) {
                logger.info("更新人脸成功");
                faceCommand.setMsg("更新人脸成功！！");
                faceCommand.setStatus(1);
                return true;
            } else {
                if (configServer.getLastErrorCode() == 1539) {
                    faceCommand.setStatus(1);
                    faceCommand.setMsg(configServer.getLastErrorMsg() + ";重新数据至人脸机！");
                    return addFace(faceCommand);
                } else {
                    logger.info("更新人脸失败");
                    faceCommand.setStatus(2);
                    faceCommand.setMsg(configServer.getLastErrorMsg());
                }
                return false;

            }
        }*/
    }

    /**
     * 人脸相机图像删除
     *
     * @param faceCommand
     * @return
     */
    public static Boolean deleteFace(FaceCommand faceCommand) {
        if (configServer != null && faceCommand != null
                && configServer.getCameraOnlineState(faceCommand.getApparatusId())
                && isRunning) {
            System.out.println("设备在线");
            if (configServer.deleteFace(faceCommand.getApparatusId(),
                    faceCommand.getFaceid(), 5000)) {
                logger.info("删除人脸成功");
                faceCommand.setStatus(1);
                return true;
            } else {
                System.out.println(configServer.getLastErrorMsg());
                logger.info("删除人脸失败");
                faceCommand.setStatus(2);
                faceCommand.setMsg(configServer.getLastErrorMsg());
                return false;
            }
        }
        return false;
    }


    public static void getFaces(String sn, ListFaceCriteria listFaceCriteria, List<Face> list) {
//        String sn = faceCommand.getApparatusId();

        if (StrUtil.isBlank(sn)) {
            logger.warn("sn为空");
            return;
        }
        boolean isOnline = configServer.getCameraOnlineState(sn);

        if (!isOnline) {
            logger.warn("{}不在线", sn);
            return;
        }

        if (!isRunning) {
            logger.warn("配置服务未启动");
            return;
        }

        if (configServer == null) {
            logger.warn("服务对象为空");
            return;
        }

        if (ObjectUtil.isEmpty(listFaceCriteria)) {
            listFaceCriteria = new ListFaceCriteria();//第一页
            logger.info("获取机器{}下学生数据开始！", sn);
        }

        FacePage facePage = configServer.listFace(sn, listFaceCriteria, 60000);//获取第一页的学生
        if (facePage == null) {
            logger.warn("{} 未获取到学生人脸", sn);
            return;
        }

        if (list == null) {
            logger.warn("人脸集合不能为空");
            return;
            //list = new ArrayList<>();
        }

        int total = facePage.getTotal();//机器总人数
        int pageNo = listFaceCriteria.getPageNo();//页码
        int pageSize = listFaceCriteria.getPageSize();//每页人数

        logger.info("从人脸相机上获取第{}页学生头像成功！总记录数{}", pageNo, total);

        if ((total - pageSize * pageNo) > 0) {
            Face[] faces = facePage.getFaces();//每页人数
            CollectionUtil.addAll(list, faces);

            pageNo++;

            listFaceCriteria.setPageNo(pageNo);

            getFaces(sn, listFaceCriteria, list);//configServer.listFace(faceCommand.getApparatusId(), listFaceCriteria, 15000);//获取PageNo页的学生

        } else {
            logger.info("已经获取到最后一页数据！");
            return;
        }

    }

    /**
     * 获取机器下的所有学生
     *
     * @param faceCommand 机器编码
     */
    public static void getFaces(FaceCommand faceCommand, List<FaceCommand> list) {
        logger.info("获取机器下的所有学生，机器是否存在" + configServer.getCameraOnlineState(faceCommand.getApparatusId()));
        if (configServer != null && faceCommand != null
                && configServer.getCameraOnlineState(faceCommand.getApparatusId())
                && isRunning) {
            ListFaceCriteria listFaceCriteria = new ListFaceCriteria();//第一页
            FacePage facePage = configServer.listFace(faceCommand.getApparatusId(), listFaceCriteria, 15000);//获取第一页的学生
            int total = facePage.getTotal();//机器总人数
            int pageNo = 1;//页码
            int pageSize = 20;//每页人数
            Boolean flag = true;
            if (total == 0) {
                flag = false;
                logger.info("相机上没有人员数据，机器编码为：" + faceCommand.getApparatusId());
            }
            while (flag) {
                if (facePage == null) {
                    continue;
                }
                Face[] faces = facePage.getFaces();//每页人数
                for (Face face : faces) {
                    FaceCommand command = new FaceCommand();
                    long time = new Date().getTime();
                    String faceid = face.getId();//学生人脸id
                    String name = face.getName();//学生名称
                    byte[][] thumbImageData = face.getThumbImageData();//人脸数据流
                    String[] paths = new String[thumbImageData.length];
                    int i = 0;
                    Boolean flage = false;
                    for (byte[] data : thumbImageData) {
                        QnyfUpload qnyfUpload = new QnyfUpload(null, null, null, null);
                        try {
                            String facePath = qnyfUpload.upload(data, String.valueOf(time) + ".jpg");
                            paths[i] = facePath;
                            logger.info("将人员头像存储在七牛云成功！图像地址" + facePath);
                            flage = true;
                            i++;
                        } catch (Exception e) {
                            // TODO: handle exception
                            command.setMsg("从人脸相机上拉取数据失败！");
                            logger.info("从人脸相机上拉取数据失败！");
                            continue;
                        }
                    }
                    command.setApparatusId(faceCommand.getApparatusId());
                    command.setCommand(faceCommand.getCommand());
                    command.setPath(paths);
                    command.setRole(face.getRole());
                    command.setFaceid(faceid);
                    command.setFaceid(name);
                    if (flage == false) {
                        command.setStatus(2);
                        command.setMsg("从人脸相机上拉取数据失败！");
                        logger.info("从人脸相机上拉取" + name + "头像失败！");
                    } else {
                        command.setStatus(1);
                        command.setMsg("从人脸相机上拉取数据成功！");
                        logger.info("从人脸相机上拉取" + name + "头像成功！图片路径为" + paths[0]);
                    }
                    list.add(command);
                }
                if ((total - pageSize * pageNo) > 0) {
                    pageNo++;
                    listFaceCriteria.setPageNo(pageNo);
                    facePage = configServer.listFace(faceCommand.getApparatusId(), listFaceCriteria, 15000);//获取PageNo页的学生
                    logger.info("从人脸相机上获取第" + pageNo + "页学生头像成功！");
                } else {
                    flag = false;
                }
            }
        }

    }
}
